package com.sinodata.bsm.cicp.collector.cics;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.CollectorUtil;
import com.sinodata.bsm.cicp.util.CommandReader;
import com.sinodata.bsm.cicp.util.FileAttribute;
import com.sinodata.bsm.common.utils.FileUtil;
import com.sinodata.bsm.common.vo.ResPropertyValue;

public class CICSLogCollector extends Collector {

    @Override
    public String[] getPropMeta() {
        return new String[] { "isNewMistake", "fileName", "Content", "timeout" };
    }

    @Override
    public String[] getParamMeta() {
        return new String[] { "filePath", "sourceFile", "errFlag", "interval" };
    }

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        if (this.getParamMeta() == null || this.getParamMeta().length < 3) {
            logger.error("Property parameter number is not correct or parameters is empty.");
            return null;
        }
        String filePath = this.getParamMap().get("filePath").trim();
        String sourceFileName = this.getParamMap().get("sourceFile").trim();
        String errFlag = this.getParamMap().get("errFlag").trim();
        String timeStr = this.getParamMap().get("interval").trim();
        if (timeStr == null || !timeStr.matches("\\d+")) {
            logger.error("Not fill in interval attribute or not fill in digital.");
            return null;
        }
        long timespace = (Long.parseLong(timeStr)) * 60 * 1000;

        String fileName = "";
        BufferedReader reader = null;
        String line = null;
        String sourceFilePathName = getFullFileName(filePath, sourceFileName);
        String cmd = "filter -f " + sourceFilePathName;
        try {
            reader = CommandReader.getReader(ip, cmd, 0, 0);
            if ((line = reader.readLine()) != null) {
                fileName = line.substring(line.lastIndexOf("/") + 1);
            } else {
                logger.error("Source file not found");
                return null;
            }
        } catch (Exception e) {
            logger.error(e);
        }
        String fullFileName = getFullFileName(filePath, fileName);
        String tmpFileName = getTmpFileName(sourceFilePathName, errFlag, ip);
        FileAttribute lastAttribute = (FileAttribute) FileUtil.readObjFromFile(tmpFileName);
        FileAttribute currentAttribute = CollectorUtil.getNewestRemoteFileByPattern(filePath, null, fileName, ip);
        if (currentAttribute == null) {
            return null;
        }
        fileName = currentAttribute.name;

        fullFileName = getFullFileName(filePath, fileName);
        List<ResPropertyValue> result = null;
        String[] propMetas = getPropMeta();
        ResPropertyValue propertyValueX = new ResPropertyValue();
        ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
        if (lastAttribute != null) {
            if (!fileName.equals(lastAttribute.name)) {
                result = readFile(fileName, fullFileName, 0, errFlag, ip, propertyValueX, propValues, propMetas, 0l);
            } else if (currentAttribute.size > lastAttribute.size) {
                result = readFile(fileName, fullFileName, lastAttribute.size, errFlag, ip, propertyValueX, propValues, propMetas, lastAttribute.lastTime);
            } else if (currentAttribute.size < lastAttribute.size) {
                result = readFile(fileName, fullFileName, 0, errFlag, ip, propertyValueX, propValues, propMetas, 0l);
            } else {
                result = new ArrayList<ResPropertyValue>();
                propValues[0] = ResPropertyValue.createPropValue("NO", propMetas[0]);
                propValues[1] = ResPropertyValue.createPropValue(fileName, propMetas[1]);
                propValues[2] = ResPropertyValue.createPropValue("N/A", propMetas[2]);
                propValues[3] = ResPropertyValue.createPropValue(0 + "", propMetas[3]);
                propertyValueX.setValues(propValues);
                result.add(propertyValueX);
            }
        } else {
            result = new ArrayList<ResPropertyValue>();
            propValues[0] = ResPropertyValue.createPropValue("NO", propMetas[0]);
            propValues[1] = ResPropertyValue.createPropValue(fileName, propMetas[1]);
            propValues[2] = ResPropertyValue.createPropValue("N/A", propMetas[2]);
            propValues[3] = ResPropertyValue.createPropValue(0 + "", propMetas[3]);
            propertyValueX.setValues(propValues);
            result.add(propertyValueX);
        }
        // 记录文件位置
        currentAttribute.name = fileName;
        if (lastAttribute == null || !lastAttribute.equals(currentAttribute)) {
            try {
                logger.info(">>>>>>write to temp file:" + tmpFileName);
                currentAttribute.lastTime = Calendar.getInstance().getTimeInMillis();
                if (lastAttribute != null) {
                    if (!lastAttribute.name.equals(currentAttribute.name)) {
                        currentAttribute.size = 0;
                    } else if ((lastAttribute.lastTime + timespace) > (Calendar.getInstance().getTimeInMillis())) {
                        currentAttribute.size = lastAttribute.size;
                        currentAttribute.lastTime = lastAttribute.lastTime;
                    }
                } else {
                    currentAttribute.size = 0;
                }
                FileUtil.forceWriteObjToFile(tmpFileName, currentAttribute, false);
            } catch (Exception e) {
                logger.error("", e);
                throw new CollectorException(e);
            }
        }
        return result;
    }

    private String getFullFileName(String path, String fileName) {
        path = path.trim();
        if (path.endsWith("/")) {
            return path + fileName;
        } else {
            return path + "/" + fileName;
        }
    }

    private String getTmpFileName(String fileName, String errFlag, String ip) {
        String path = "tmp/";
        StringBuffer buffer = new StringBuffer();
        buffer.append(ip).append("_").append(fileName).append("_").append(errFlag);
        return path + FileUtil.validateFileName(buffer.toString());
    }

    /**
     * 从文件的某个位置开始读，直至文件结束
     *
     * @param fileName
     * @param readStart
     * @param ip
     * @return
     */
    private List<ResPropertyValue> readFile(String fileName, String fullFileName, long readStart, String filterPattern, String ip, ResPropertyValue propertyValueX, ResPropertyValue.PropValue[] propValues, String[] propMetas, long time) {
        BufferedReader reader = null;
        String cmd = "filter -f " + fullFileName + " -s " + readStart;
        if (filterPattern != null) {
            cmd = cmd + " -p '" + filterPattern + "'";
        }
        List<ResPropertyValue> result = new ArrayList<ResPropertyValue>();
        try {
            reader = CommandReader.getReader(ip, cmd, 0, 0);
            String line;
            int count = 0;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.length() > 0) {
                    count++;
                    propertyValueX = new ResPropertyValue();
                    propValues = new ResPropertyValue.PropValue[propValues.length];
                    propValues[0] = ResPropertyValue.createPropValue("YES", propMetas[0]);
                    propValues[1] = ResPropertyValue.createPropValue(fileName, propMetas[1]);
                    propValues[2] = ResPropertyValue.createPropValue(line, propMetas[2]);
                    propValues[3] = ResPropertyValue.createPropValue(count + "", propMetas[3]);
                    propertyValueX.setValues(propValues);
                    result.add(propertyValueX);
                }
            }
            if (result.size() == 0) {
                propValues[0] = ResPropertyValue.createPropValue("NO", propMetas[0]);
                propValues[1] = ResPropertyValue.createPropValue(fileName, propMetas[1]);
                propValues[2] = ResPropertyValue.createPropValue("N/A", propMetas[2]);
                propValues[3] = ResPropertyValue.createPropValue(0 + "", propMetas[3]);
                propertyValueX.setValues(propValues);
                result.add(propertyValueX);
            }
            return result;
        } catch (IOException e) {
            logger.error("", e);
            return null;
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception ex) {
                }
            }
        }
    }

}
